/*!
 * \file WTSContractInfo.hpp
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief 合约信息和品种信息数据结构定义文件
 */
#pragma once
#include "WTSObject.hpp"
#include "WTSTypes.h"
#include "FasterDefs.h"
#include <string>
#include <sstream>

NS_WTP_BEGIN
class WTSSessionInfo;

/*!
 * \brief 商品信息类，用于存储和管理交易品种的基础信息
 * 
 * \details 该类封装了交易品种的完整信息，包括：
 *          - 品种基本属性：名称、交易所、产品ID等
 *          - 交易参数：最小价格变动单位、合约乘数等
 *          - 交易规则：交易模式、平仓方式等
 *          - 会话信息：交易时段和模板信息
 *          主要用于系统中各个模块对品种信息的查询和使用
 * 
 * \author Wesley
 * \date 2020/03/30
 */
class WTSCommodityInfo: public WTSObject
{
public:
	/*!
	 * \brief 创建商品信息对象的静态工厂方法
	 * 
	 * \details 通过传入的参数创建一个商品信息对象，并自动生成完整的产品ID
	 * 
	 * \param pid 产品ID（如IF、IC、IH等）
	 * \param name 商品名称（如沪深300股指期货）
	 * \param exchg 交易所代码（如CFFEX、SHFE等）
	 * \param session 交易时段模板ID
	 * \param trdtpl 交易日历模板ID
	 * \param currency 计价货币，默认为"CNY"人民币
	 * 
	 * \return 创建成功的商品信息对象指针
	 * 
	 * \note 返回的对象需要调用者负责内存管理
	 */
	static WTSCommodityInfo* create(const char* pid, const char* name, const char* exchg, const char* session, const char* trdtpl, const char* currency = "CNY")
	{
		WTSCommodityInfo* ret = new WTSCommodityInfo;
		ret->m_strName = name;
		ret->m_strExchg = exchg;
		ret->m_strProduct = pid;
		ret->m_strCurrency = currency;
		ret->m_strSession = session;
		ret->m_strTrdTpl = trdtpl;

		std::stringstream ss;
		ss << exchg << "." << pid;
		ret->m_strFullPid = ss.str();

		return ret;
	}

	/*!
	 * \brief 设置合约乘数
	 * 
	 * \details 合约乘数用于计算合约价值，如股指期货每点价值300元
	 * 
	 * \param volScale 合约乘数值
	 */
	inline void	setVolScale(uint32_t volScale){ m_uVolScale = volScale; }
	
	/*!
	 * \brief 设置最小价格变动单位
	 * 
	 * \details 设置该品种的最小价格变动单位（价格精度），如0.2点
	 * 
	 * \param pxTick 最小价格变动单位
	 */
	inline void	setPriceTick(double pxTick){ m_dPriceTick = pxTick; }
	
	/*!
	 * \brief 设置合约类别
	 * 
	 * \details 设置合约的分类类型，如期货、股票、期权等
	 * 
	 * \param cat 合约类别枚举值
	 */
	inline void	setCategory(ContractCategory cat){ m_ccCategory = cat; }
	
	/*!
	 * \brief 设置平仓模式
	 * 
	 * \details 设置该品种的平仓方式，如平今、平昨等
	 * 
	 * \param cm 平仓模式枚举值
	 */
	inline void	setCoverMode(CoverMode cm){ m_coverMode = cm; }
	
	/*!
	 * \brief 设置价格模式
	 * 
	 * \details 设置价格计算模式，影响盈亏计算方式
	 * 
	 * \param pm 价格模式枚举值
	 */
	inline void	setPriceMode(PriceMode pm){ m_priceMode = pm; }
	
	/*!
	 * \brief 设置交易模式
	 * 
	 * \details 设置该品种的交易模式，如双向交易、只能做多等
	 * 
	 * \param tm 交易模式枚举值
	 */
	inline void	setTradingMode(TradingMode tm) { m_tradeMode = tm; }

	/*!
	 * \brief 判断是否可以做空
	 * 
	 * \details 根据交易模式判断该品种是否支持卖空操作
	 * 
	 * \return true表示可以做空，false表示不可以做空
	 */
	inline bool canShort() const { return m_tradeMode == TM_Both; }
	
	/*!
	 * \brief 判断是否为T+1交易
	 * 
	 * \details 判断该品种是否为T+1交易模式（当日买入次日才能卖出）
	 * 
	 * \return true表示T+1交易，false表示T+0交易
	 */
	inline bool isT1() const { return m_tradeMode == TM_LongT1; }

	/*!
	 * \brief 获取商品名称
	 * 
	 * \return 商品名称字符串指针
	 */
	inline const char* getName()	const{ return m_strName.c_str(); }
	
	/*!
	 * \brief 获取交易所代码
	 * 
	 * \return 交易所代码字符串指针
	 */
	inline const char* getExchg()	const{ return m_strExchg.c_str(); }
	
	/*!
	 * \brief 获取产品ID
	 * 
	 * \return 产品ID字符串指针
	 */
	inline const char* getProduct()	const{ return m_strProduct.c_str(); }
	
	/*!
	 * \brief 获取计价货币
	 * 
	 * \return 计价货币字符串指针
	 */
	inline const char* getCurrency()	const{ return m_strCurrency.c_str(); }
	
	/*!
	 * \brief 获取交易时段模板ID
	 * 
	 * \return 交易时段模板ID字符串指针
	 */
	inline const char* getSession()	const{ return m_strSession.c_str(); }
	
	/*!
	 * \brief 获取交易日历模板ID
	 * 
	 * \return 交易日历模板ID字符串指针
	 */
	inline const char* getTradingTpl()	const{ return m_strTrdTpl.c_str(); }
	
	/*!
	 * \brief 获取完整产品ID
	 * 
	 * \details 返回格式为"交易所.产品ID"的完整标识符，如"CFFEX.IF"
	 * 
	 * \return 完整产品ID字符串指针
	 */
	inline const char* getFullPid()	const{ return m_strFullPid.c_str(); }

	/*!
	 * \brief 获取合约乘数
	 * 
	 * \return 合约乘数值
	 */
	inline uint32_t	getVolScale()	const{ return m_uVolScale; }
	
	/*!
	 * \brief 获取最小价格变动单位
	 * 
	 * \return 最小价格变动单位
	 */
	inline double	getPriceTick()	const{ return m_dPriceTick; }

	/*!
	 * \brief 获取合约类别
	 * 
	 * \return 合约类别枚举值
	 */
	inline ContractCategory		getCategoty() const{ return m_ccCategory; }
	
	/*!
	 * \brief 获取平仓模式
	 * 
	 * \return 平仓模式枚举值
	 */
	inline CoverMode			getCoverMode() const{ return m_coverMode; }
	
	/*!
	 * \brief 获取价格模式
	 * 
	 * \return 价格模式枚举值
	 */
	inline PriceMode			getPriceMode() const{ return m_priceMode; }
	
	/*!
	 * \brief 获取交易模式
	 * 
	 * \return 交易模式枚举值
	 */
	inline TradingMode			getTradingMode() const { return m_tradeMode; }

	/*!
	 * \brief 添加合约代码到该品种
	 * 
	 * \details 将一个合约代码添加到该品种的合约集合中
	 * 
	 * \param code 合约代码，如"IF2312"
	 */
	inline void		addCode(const char* code){ m_setCodes.insert(code); }
	
	/*!
	 * \brief 获取该品种下所有合约代码集合
	 * 
	 * \return 合约代码集合的常量引用
	 */
	inline const CodeSet& getCodes() const{ return m_setCodes; }

	/*!
	 * \brief 设置最小手数变动单位
	 * 
	 * \details 设置该品种的最小交易数量变动单位
	 * 
	 * \param lotsTick 最小手数变动单位
	 */
	inline void	setLotsTick(double lotsTick){ m_dLotTick = lotsTick; }
	
	/*!
	 * \brief 设置最小交易手数
	 * 
	 * \details 设置该品种允许的最小交易数量
	 * 
	 * \param minLots 最小交易手数
	 */
	inline void	setMinLots(double minLots) { m_dMinLots = minLots; }

	/*!
	 * \brief 判断是否为期权品种
	 * 
	 * \details 根据合约类别判断是否为期权类品种（期货期权、ETF期权、现货期权）
	 * 
	 * \return true表示是期权品种，false表示不是期权品种
	 */
	inline bool isOption() const
	{
		return (m_ccCategory == CC_FutOption || m_ccCategory == CC_ETFOption || m_ccCategory == CC_SpotOption);
	}

	/*!
	 * \brief 判断是否为期货品种
	 * 
	 * \details 根据合约类别判断是否为期货品种
	 * 
	 * \return true表示是期货品种，false表示不是期货品种
	 */
	inline bool isFuture() const
	{
		return m_ccCategory == CC_Future;
	}

	/*!
	 * \brief 判断是否为股票品种
	 * 
	 * \details 根据合约类别判断是否为股票品种
	 * 
	 * \return true表示是股票品种，false表示不是股票品种
	 */
	inline bool isStock() const
	{
		return m_ccCategory == CC_Stock;
	}

	/*!
	 * \brief 获取最小手数变动单位
	 * 
	 * \return 最小手数变动单位
	 */
	inline double	getLotsTick() const { return m_dLotTick; }
	
	/*!
	 * \brief 获取最小交易手数
	 * 
	 * \return 最小交易手数
	 */
	inline double	getMinLots() const { return m_dMinLots; }

	/*!
	 * \brief 设置交易时段信息对象
	 * 
	 * \details 关联该品种的交易时段信息对象
	 * 
	 * \param sInfo 交易时段信息对象指针
	 */
	inline void		setSessionInfo(WTSSessionInfo* sInfo) { m_pSession = sInfo; }
	
	/*!
	 * \brief 获取交易时段信息对象
	 * 
	 * \return 交易时段信息对象指针
	 */
	inline WTSSessionInfo* getSessionInfo() const { return m_pSession; }

private:
	std::string	m_strName;		//品种名称
	std::string	m_strExchg;		//交易所代码
	std::string	m_strProduct;	//品种ID
	std::string	m_strCurrency;	//货币
	std::string m_strSession;	//交易时段模板
	std::string m_strTrdTpl;	//交易日历模板
	std::string m_strFullPid;	//全品种ID，格式如CFFEX.IF

	uint32_t	m_uVolScale;	//合约乘数
	double		m_dPriceTick;	//最小价格变动单位

	double		m_dLotTick;		//最小手数变动单位
	double		m_dMinLots;		//最小交易手数

	ContractCategory	m_ccCategory;	//品种分类，期货、股票、期权等
	CoverMode			m_coverMode;	//平仓方式
	PriceMode			m_priceMode;	//价格模式
	TradingMode			m_tradeMode;	//交易模式

	CodeSet				m_setCodes;		//该品种下的合约代码集合

	WTSSessionInfo*		m_pSession;		//交易时段信息对象
};

/*!
 * \brief 合约信息类，用于存储和管理具体合约的详细信息
 * 
 * \details 该类封装了单个交易合约的完整信息，包括：
 *          - 合约基本属性：代码、名称、交易所、所属品种等
 *          - 交易限制：最大市价单数量、最大限价单数量等
 *          - 关联信息：所属商品信息对象引用
 *          主要用于订单下单、风控检查等场景中的合约信息查询
 * 
 * \author Wesley
 * \date 2020/03/30
 */
class WTSContractInfo :	public WTSObject
{
public:
	/*!
	 * \brief 创建合约信息对象的静态工厂方法
	 * 
	 * \details 通过传入的参数创建一个合约信息对象，并自动生成完整的合约代码和品种ID
	 * 
	 * \param code 合约代码（如IF2312、000001）
	 * \param name 合约名称（如沪深300股指期货2312、平安银行）
	 * \param exchg 交易所代码（如CFFEX、SSE等）
	 * \param pid 所属产品ID（如IF、000001等）
	 * 
	 * \return 创建成功的合约信息对象指针
	 * 
	 * \note 返回的对象需要调用者负责内存管理
	 */
	static WTSContractInfo* create(const char* code, const char* name, const char* exchg, const char* pid)
	{
		WTSContractInfo* ret = new WTSContractInfo;
		ret->m_strCode = code;
		ret->m_strName = name;
		ret->m_strProduct = pid;
		ret->m_strExchg = exchg;

		std::stringstream ss;
		ss << exchg << "." << code;
		ret->m_strFullCode = ss.str();

		std::stringstream sss;
		sss << exchg << "." << pid;
		ret->m_strFullPid = sss.str();

		return ret;
	}

	/*!
	 * \brief 设置交易数量限制
	 * 
	 * \details 设置该合约的市价单和限价单最大允许交易数量，用于风控检查
	 * 
	 * \param maxMarketVol 最大市价单数量（手）
	 * \param maxLimitVol 最大限价单数量（手）
	 */
	inline void	setVolumeLimits(uint32_t maxMarketVol, uint32_t maxLimitVol)
	{
		m_maxMktQty = maxMarketVol;
		m_maxLmtQty = maxLimitVol;
	}

	/*!
	 * \brief 获取合约代码
	 * 
	 * \return 合约代码字符串指针
	 */
	inline const char* getCode()	const{return m_strCode.c_str();}
	
	/*!
	 * \brief 获取交易所代码
	 * 
	 * \return 交易所代码字符串指针
	 */
	inline const char* getExchg()	const{return m_strExchg.c_str();}
	
	/*!
	 * \brief 获取合约名称
	 * 
	 * \return 合约名称字符串指针
	 */
	inline const char* getName()	const{return m_strName.c_str();}
	
	/*!
	 * \brief 获取所属产品ID
	 * 
	 * \return 产品ID字符串指针
	 */
	inline const char* getProduct()	const{return m_strProduct.c_str();}

	/*!
	 * \brief 获取完整合约代码
	 * 
	 * \details 返回格式为"交易所.合约代码"的完整标识符，如"CFFEX.IF2312"
	 * 
	 * \return 完整合约代码字符串指针
	 */
	inline const char* getFullCode()	const{ return m_strFullCode.c_str(); }
	
	/*!
	 * \brief 获取完整产品ID
	 * 
	 * \details 返回格式为"交易所.产品ID"的完整标识符，如"CFFEX.IF"
	 * 
	 * \return 完整产品ID字符串指针
	 */
	inline const char* getFullPid()	const{ return m_strFullPid.c_str(); }

	/*!
	 * \brief 获取最大市价单数量
	 * 
	 * \return 最大市价单数量（手）
	 */
	inline uint32_t	getMaxMktVol() const{ return m_maxMktQty; }
	
	/*!
	 * \brief 获取最大限价单数量
	 * 
	 * \return 最大限价单数量（手）
	 */
	inline uint32_t	getMaxLmtVol() const{ return m_maxLmtQty; }

	/*!
	 * \brief 设置关联的商品信息对象
	 * 
	 * \details 将该合约与其所属的商品信息对象进行关联
	 * 
	 * \param commInfo 商品信息对象指针
	 */
	inline void setCommInfo(WTSCommodityInfo* commInfo) { m_commInfo = commInfo; }
	
	/*!
	 * \brief 获取关联的商品信息对象
	 * 
	 * \return 商品信息对象指针，如果未设置则返回NULL
	 */
	inline WTSCommodityInfo* getCommInfo() const { return m_commInfo; }

protected:
	/*!
	 * \brief 默认构造函数
	 * 
	 * \details 初始化商品信息指针为NULL
	 */
	WTSContractInfo():m_commInfo(NULL){}
	
	/*!
	 * \brief 虚析构函数
	 * 
	 * \details 确保派生类能够正确析构
	 */
	virtual ~WTSContractInfo(){}

private:
	std::string	m_strCode;		//合约代码
	std::string	m_strExchg;		//交易所代码
	std::string	m_strName;		//合约名称
	std::string	m_strProduct;	//所属产品ID

	std::string m_strFullPid;	//完整产品ID
	std::string m_strFullCode;	//完整合约代码

	uint32_t	m_maxMktQty;	//最大市价单数量
	uint32_t	m_maxLmtQty;	//最大限价单数量

	WTSCommodityInfo*	m_commInfo;	//关联的商品信息对象
};


NS_WTP_END